package semantic.tables;

import java.util.HashMap;
import java.util.Map;

import syntaxtree.Type;

public class ClassTable {

	private final ProgramTable programTable;
	private final Map<Symbol, Type> vars = new HashMap<Symbol, Type>();
	private final Map<Symbol, MethodTable> methods = new HashMap<Symbol, MethodTable>();
	public final Symbol id;
	public final Symbol superClass;

	public ClassTable(String id, ProgramTable programTable) {
		this.programTable = programTable;
		this.id = Symbol.symbol(id);
		superClass = null;
	}

	public ClassTable(String id, String superClass, ProgramTable programTable) {
		this.programTable = programTable;
		this.id = Symbol.symbol(id);
		this.superClass = Symbol.symbol(superClass);
	}

	public boolean addVar(String key, Type value) {
		if (vars.containsKey(Symbol.symbol(key))) {
			return false;
		}
		vars.put(Symbol.symbol(key), value);
		return true;
	}

	public boolean addMethod(String key, MethodTable value) {
		if (methods.containsKey(Symbol.symbol(key))) {
			return false;
		}
		methods.put(Symbol.symbol(key), value);
		return true;
	}

	public MethodTable getMethod(String key) {
		return methods.get(Symbol.symbol(key));
	}

	/**
	 * Finds for the variable in the entire class hierarchy
	 * 
	 * @param key
	 * @return
	 */
	public Type getVarType(String key) {
		Symbol keySymbol = Symbol.symbol(key);
		ClassTable classTable = this;
		while (classTable != null) {
			Type type = classTable.vars.get(keySymbol);
			if (type != null) {
				return type;
			}
			if (classTable.superClass == null) {
				return null;
			} else {
				classTable = programTable.getClass(classTable.superClass.toString());
			}
		}
		return null;
	}

	public Map<Symbol, Type> getVars() {
		return vars;
	}

}
